import java.util.ArrayList;
import java.util.List;

/**
 * LeetCode 78. 子集
 */
public class Solution_78 {
    List<List<Integer>> ans = new ArrayList<>();
    List<Integer> temp = new ArrayList<>();

    /**
     * 方法二：回溯递归枚举
     * <p>
     * 时间复杂度：O(n * 2^n)
     * <p>
     * 空间复杂度：O(n)
     */
    public List<List<Integer>> subsets(int[] nums) {
        dfs(0, nums);
        return ans;
    }

    private void dfs(int cur, int[] nums) {
        if (cur == nums.length) {
            ans.add(new ArrayList<>(temp));
            return;
        }
        temp.add(nums[cur]);
        dfs(cur + 1, nums);
        temp.remove(temp.size() - 1);
        dfs(cur + 1, nums);
    }

    /**
     * 方法一：位运算迭代枚举
     * <p>
     * 时间复杂度：O(n * 2^n)
     * <p>
     * 空间复杂度：O(n)
     */
    public List<List<Integer>> subsets1(int[] nums) {
        List<List<Integer>> ans = new ArrayList<>();
        List<Integer> temp = new ArrayList<>();

        int n = nums.length;
        // 共 2^n - 1 个子集
        // 每个子集可以对应一个长度为 n 的 01 序列，第 i 位表示 nums[i] 是否在子集中
        for (int mask = 0; mask < (1 << n); mask++) {
            temp.clear();
            for (int i = 0; i < n; i++) {
                if ((mask & (1 << i)) != 0) {
                    temp.add(nums[i]);
                }
            }
            ans.add(new ArrayList<>(temp));
        }
        return ans;
    }
}
